<template>
  <el-form ref="formRef" :inline="true" :label-position="formContext.labelPosition">
    <el-row ref="resizeRef" :gutter="gutter" class="query-form-row">
      <template v-if="items">
        <QueryFormItem v-for="(item, index) in items" :key="index" :field="item" :form-data="formData"/>
      </template>
      <slot/>
      <el-col v-if="showControl" :span="controlSpan" class="form-item-control">
        <el-form-item>
          <template v-if="showControlLabel" #label> &nbsp;</template>
          <slot :collapse="collapse"
                :overflow="overflow"
                :toggleCollapse="toggleCollapse"
                name="control"/>
          <div v-if="overflow" class="query-collapse-button" @click="toggleCollapse()">
            <el-button link type="primary">
              {{ collapse ? $t('form.expand') : $t('form.shrink') }}
              <i class="icon">
                <SvgIcon :icon="collapse ? 'ep:arrow-down' : 'ep:arrow-up'"/>
              </i>
            </el-button>
          </div>
        </el-form-item>
      </el-col>
    </el-row>
  </el-form>
</template>

<script lang="ts" setup>
import { computed, getCurrentInstance, PropType, provide, ref, watch, } from 'vue';
import { useResize } from '@/hooks/use-resize';
import { BreakpointsSpan, LabelPosition, useSpanConfig, } from '@/components/query-form/hook/use-span-config';
import useOrderedChildren from '@/hooks/use-ordered-children';
import { beforeDebounce } from '@/utils/util';
import type { ResizeCallBack } from '@/utils/resize-event.ts';
import type { FormInstance, RowInstance } from 'element-plus';
import type { FormItemData, QueryFormItemRule, QueryFormProvide, } from '@/components/query-form/constants.ts';
import { formContextKey } from '@/components/query-form/constants';
import { SvgIcon } from '@/components/icon';
import QueryFormItem from '@/components/query-form/query-form-item.vue';

const props = defineProps({
  formData: Object,
  labelPosition: {
    type: String as PropType<LabelPosition>,
    values: ['left', 'right', 'top'],
    default: 'right',
  },
  span: {
    type: [Number, Array] as PropType<number | BreakpointsSpan>,
    default: null,
  },
  gutter: {
    type: Number,
    default: 16,
  },
  showControl: {
    type: Boolean,
    default: false,
  },
  items: {
    type: Array as PropType<QueryFormItemRule[]>,
    default: () => [],
  }
});
const formRef = ref<FormInstance>();
const width = ref();
const resizeRef = ref<RowInstance>();
const collapse = ref(true);
const overflow = ref(false);
const formContext = useSpanConfig(width, props.span, props.labelPosition);
const instance = getCurrentInstance();
const {
  children: formItems,
  addChild: registerForm,
  removeChild: unregisterForm,
} = useOrderedChildren<FormItemData>(instance!, 'QueryFormItem');

const updateWidth = beforeDebounce(({target}) => {
  const client = target.getBoundingClientRect();
  // 这个地方修改为 必须宽度 > 0 才进行变更
  if (client.width > 0) {
    width.value = client.width;
  }
}, 10);

useResize(resizeRef, updateWidth as ResizeCallBack);

provide<QueryFormProvide>(formContextKey, {
  formItems,
  registerForm,
  unregisterForm,
  form: formContext,
  overflow: overflow.value,
});

const controlSpan = computed(() => {
  const {span} = formContext.value;
  return span;
});

const showControlLabel = computed(() => {
  const {span, labelPosition} = formContext.value;
  if (span === 24 && labelPosition === 'top') {
    return false;
  }
  return true;
});

watch([collapse, formContext.value, () => formItems.value], () => {
  if (props.showControl !== true) {
    return;
  }
  const span = formContext.value.span;
  let spanSum = span;
  overflow.value = false;
  formItems.value.forEach((item, index) => {
    item.index = index;
    spanSum += span;

    item.visible = false;
    if (spanSum > 24) {
      overflow.value = true;
      if (collapse.value && index > 0) {
        item.visible = true;
      }
    }
  });
});

const toggleCollapse = () => {
  collapse.value = !collapse.value;
};

defineExpose({
  formRef,
});
</script>

<style lang="scss" scoped>
.query-form-row {
  width: 100%;

  .form-item-control {
    margin-right: 0;
    margin-left: auto;
    display: inline-flex;
    align-items: start;
    justify-content: end;

    :deep(.el-form-item) {
      margin-bottom: 16px;
      margin-right: 0;

      .el-form-item__label {
        flex: 0 1 auto;
      }

      .el-form-item__content {
        flex: 1 0 auto;
      }

      .el-button + .el-button {
        margin-left: 12px;
      }

      .query-collapse-button {
        margin-left: 12px;

        > button {
          letter-spacing: 1px;
        }

        .svg-icon {
          margin-left: 3px;
        }
      }
    }
  }

  :deep(.query-form-item) {
    box-sizing: border-box;

    .el-form-item {
      margin-bottom: 16px;
      margin-right: 0;
      width: 100%;

      .el-form-item__content {
        .el-input,
        .el-select {
          width: 100%;
        }
      }
    }
  }
}
</style>
